package org.xxpay.pay.channel.funpay;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.domain.api.AbstractRes;
import org.xxpay.core.common.domain.api.ApiBuilder;
import org.xxpay.core.common.domain.api.PayRes;
import org.xxpay.core.common.domain.api.msg.QueryRetMsg;
import org.xxpay.core.common.util.AmountUtil;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.common.util.PayDigestUtil;
import org.xxpay.core.common.util.XXPayUtil;
import org.xxpay.core.common.vo.DBApplicationConfig;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayment;

import java.util.HashMap;
import java.util.Map;

@Service
public class FunpayPaymentService extends BasePayment {

    private static final MyLog _log = MyLog.getLog(FunpayPaymentService.class);

    @Override
    public String getChannelName() {
        return FunpayConfig.CHANNEL_NAME;
    }

    @Override
    public AbstractRes pay(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        switch (channelId) {
            case FunpayConfig.CHANNEL_TYPE_WX_H5 :
                return doPay(payOrder, "sfwx");
            case FunpayConfig.CHANNEL_TYPE_ALI_H5 :
                return doPay(payOrder, "yunal");
            default:
                return ApiBuilder.bizError("不支持的渠道[channelId="+channelId+"]");
        }
    }


    /** 支付请求 **/
    private AbstractRes doPay(PayOrder payOrder, String payType) {

        String logPrefix = "["+ FunpayConfig.CHANNEL_NAME + "下单]";
        String payOrderId = payOrder.getPayOrderId();
        try {

            FunpayConfig funpayConfig = new FunpayConfig(getPayParam(payOrder));

            DBApplicationConfig dbConfig = getDBApplicationConfig();

            PayRes retObj = ApiBuilder.buildSuccess(PayRes.class);
            // 订单参数
            Map<String, String> paramsMap = new HashMap<>();
            paramsMap.put("method", "bill.trade.nobank");                                          // 接口服务码
            paramsMap.put("mchId", funpayConfig.getMchId());                                       // 商户号
            paramsMap.put("amount", AmountUtil.convertCent2Dollar(payOrder.getAmount()+""));    //订单金额
            paramsMap.put("appType", payType);                                                     // 银行编码
            paramsMap.put("orderId", payOrderId);                                                  // 订单号
            paramsMap.put("userIp", payOrder.getClientIp());                                       // ip
            paramsMap.put("notifyUrl", super.getNotifyUrl(getChannelName(), dbConfig));            //服务端通知
            paramsMap.put("returnUrl", super.getReturnUrl(getChannelName(), dbConfig));            //页面跳转通知
            // 订单签名
            paramsMap.put("sign", PayDigestUtil.getSign(paramsMap, funpayConfig.getKey()).toLowerCase());         //签名

            //发起下单请求
            String reqData = XXPayUtil.genUrlParams2(paramsMap);
            String reqUrl = funpayConfig.getReqUrl() + "/api/gateway?" + reqData; //请求网关地址
            _log.info("{}请求地址:{}", logPrefix, reqUrl);
            String result = XXPayUtil.call4Post(reqUrl);
            _log.info("{}返回数据:{}", logPrefix, result);
            if(StringUtils.isBlank(result)) {
                return ApiBuilder.bizError("上游通道返回空!");
            }

            JSONObject resObj = JSONObject.parseObject(result);

            String code = resObj.getString("code");
            String msg = resObj.getString("msg");
            if(!"SUCCESS".equals(code)) {
                return ApiBuilder.bizError("调用通道下单失败!返回:" + msg);
            }

            // 请求地址
            String toPayUrl = resObj.getString("payUrl");
            String channelOrderId = resObj.getString("tradeNo");

            retObj.setPayJumpUrl(toPayUrl);      // 可以通过该地址跳转到支付中心界面完成支付(URL)
            StringBuffer payForm = new StringBuffer();
            payForm.append("<script>window.location.href = '"+toPayUrl+"';</script>");

            retObj.setPayUrl(payForm.toString());
            retObj.setPayMethod(PayConstant.PAY_METHOD_FORM_JUMP);

            int updateCount = commonService.payOrderService.updateStatus4Ing(payOrder.getPayOrderId(), channelOrderId);
            _log.info("[{}]更新订单状态为支付中:payOrderId={},result={}", getChannelName(), payOrder.getPayOrderId(), updateCount);

            return retObj;

        } catch (Exception e) {
            _log.error("{}异常， orderId={}", logPrefix, payOrderId, e);
            return ApiBuilder.bizError("调起接口失败!["+e.getMessage()+"]");
        }
    }

    @Override
    public QueryRetMsg query(PayOrder payOrder) {
        String logPrefix = "["+ FunpayConfig.CHANNEL_NAME + "查单]";
        String payOrderId = payOrder.getPayOrderId();
        _log.info("{}开始查询,payOrderId={}", logPrefix, payOrderId);
        FunpayConfig funpayConfig = new FunpayConfig(getPayParam(payOrder));
        JSONObject retObj = buildRetObj();
        retObj.put("status", 1);    // 支付中

        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("mchId", funpayConfig.getMchId());
        paramMap.put("method", "bill.query");
        paramMap.put("orderId", payOrderId);
        try{
            // 生成签名
            String sign = PayDigestUtil.getSign(paramMap, funpayConfig.getKey());
            paramMap.put("sign", sign);             // 签名
            _log.info("{}请求数据:{}", getChannelName(), paramMap);
            String url = funpayConfig.getReqUrl() + "/api/gateway?";
            String result = XXPayUtil.call4Post(url + paramMap);
            _log.info("{}返回数据:{}", getChannelName(), result);
            JSONObject json = JSONObject.parseObject(result);
            String code = json.getString("code");
            String msg = json.getString("msg");
            if (!"SUCCESS".equalsIgnoreCase(code)) {
                _log.info("{}请求返回状态失败:code={},msg={}", getChannelName(), result, msg);
                return QueryRetMsg.waiting();  //支付中
            }
            String status = json.getString("status");
            if ("SUCCESS".equalsIgnoreCase(status)) {
                return QueryRetMsg.confirmSuccess(null);  // 成功
            }else if ("CLOSED".equalsIgnoreCase(status)) {
                return QueryRetMsg.confirmFail();          // 失败
            }
            return QueryRetMsg.waiting();  //支付中
        }catch (Exception e){
            _log.error(e, FunpayConfig.CHANNEL_NAME+"查询异常");
        }
        return QueryRetMsg.waiting();  //支付中
    }

}
